
package ogame.reader;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import ogame.utilities.Constants;
import ogame.utilities.Coords;
import ogame.utilities.planets.Planet;
import ogame.utilities.Player;
import ogame.utilities.research.Research;
import ogame.utilities.research.ResearchType;
import ogame.utilities.Resources;
import ogame.utilities.buildings.BuildingType;
import ogame.utilities.buildings.Buildings;
import ogame.utilities.defenses.DefenseType;
import ogame.utilities.defenses.Defenses;
import ogame.utilities.ships.ShipType;
import ogame.utilities.ships.Ships;

/**
 *
 * @author scchang
 */
public class OgamePlanetReader extends JPanel implements ActionListener{
    
    protected LinkedList<OgamePlanetReaderListener> listeners;
    protected JTextArea inputArea;
    protected JButton parseButton;
    
    public OgamePlanetReader(){
        this.setPreferredSize(new Dimension(Constants.READER_SIZE_WIDTH, 
                Constants.READER_SIZE_HEIGHT));
        this.setFocusable(true);
        
        GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints c = new GridBagConstraints();
        this.setLayout(gridbag);
        
        c.gridwidth = GridBagConstraints.RELATIVE;
        
        this.inputArea = new JTextArea(Constants.READER_TEXT_ROWS, 
                Constants.READER_TEXT_COLS);
        this.add(new JScrollPane(this.inputArea), c);
        
        c.fill = GridBagConstraints.BOTH;
        c.gridwidth = GridBagConstraints.REMAINDER;
        
        this.parseButton = new JButton("Read");
        this.parseButton.addActionListener(this);
        this.add(this.parseButton, c);
        
        this.listeners = new LinkedList();
    }
    
    public void actionPerformed(ActionEvent e){
        System.out.println("Read Requested.");
        String txt = this.inputArea.getText();
        if(txt == null){
            return;
        }
        
        Planet planet = null;
        planet = this.parseInputArea(txt);
        this.notifyOgameReaderListeners(planet);
    }
    
    protected Planet parseInputArea(String txt){
        Planet planet = null;
        // Process input string
        String splits[] = txt.split("[\n\t]");
        
        for(int i = 0; i < splits.length; ++i){
            splits[i] = splits[i].replace(" ", "");
            splits[i] = splits[i].replace(".", "");
        }
        
        // Get General Information
        Player player = this.parsePlayer(splits);
        Coords coord = this.parseCoords(txt);
        String planetName = this.parsePlanetName(splits);
        
        if(coord != null && planetName != null){
            planet = new Planet(player, planetName, coord);
            player.addPlanet(planet);
        }
        

        // Parse Resources
        Resources res = this.parseResources(splits);
        
        if(planet != null){
            planet.setResources(res);
        }
        
        // Parse Research
        Research research = this.parseResearch(splits);
        
        if(research != null ){
            player.setResearch(research);
        }
        
        // Parse Ships
        Ships ships = this.parseShips(splits);
        
        if(ships != null){
            planet.setShips(ships);
        }

        // Parse buildings
        Buildings buildings = this.parseBuildings(splits);
        
        if(buildings != null){
            planet.setBuildings(buildings);
        }
        
        // Parse defense
        Defenses defenses = this.parseDefenses(splits);
        
        if(defenses != null){
            planet.setDefenses(defenses);
        }
        
        System.out.println(planet);
        return planet;
    }
    
    protected Defenses parseDefenses(String splits[]){
        Defenses defenses = new Defenses();
        for(DefenseType defense: DefenseType.values()){
            // Convert by remvoing space
            String desired = defense.name().replace("_", "");
            for(int i = 0; i < splits.length; ++i){
                if(splits[i].toUpperCase().replace("-", "").equals(desired)){
                    System.out.println("Next" + splits[i+1]);
                    defenses.put(defense, Integer.parseInt(splits[i+1]));
                }
            }
        }
        return defenses;
    }
    
    protected Buildings parseBuildings(String splits[]){
        Buildings buildings = new Buildings();
        for(BuildingType building:BuildingType.values()){
            // Convert by removing psace
            String desired = building.name().replace("_", "");
            for(int i = 0; i < splits.length; ++i){
                if(splits[i].toUpperCase().equals(desired)){
                    buildings.put(building, Integer.parseInt(splits[i+1]));
                }
            }
        }
        return buildings;
    }
    
    protected Ships parseShips(String splits[]){
        Ships ships = new Ships();
        for(ShipType ship:ShipType.values()){
            //  Convert by removing space
            String desired = ship.name().replace("_", "");
            for(int i = 0; i < splits.length; ++i){
                if(splits[i].toUpperCase().equals(desired)){
                    ships.put(ship, Integer.parseInt(splits[i+1]));
                }
            }
        }
        return ships;
    }
    
    protected Research parseResearch(String splits[]){
        Research totalResearch = new Research();
        for(ResearchType research:ResearchType.values()){
            // Convert by removing spaces
            String desired = research.name().replace("_", "");
            for(int i = 0; i < splits.length; ++i){
                if(splits[i].toUpperCase().equals(desired)){
                    totalResearch.put(research, Integer.parseInt(splits[i+1]));
                }
            }
        }
        return totalResearch;
    }
    

    protected Player parsePlayer(String splits[]){
        // First find name of player
        int startIndex = splits[0].indexOf("(");
        int endIndex = splits[0].indexOf(")");
        if(startIndex != -1 && endIndex != -1){
            startIndex += 8;
            String name = splits[0].substring(startIndex, endIndex);
            return new Player(name);
        }else{
            System.out.println("Unable to find player's name.");
            return null;
        }
    }
    
    protected Coords parseCoords(String txt){
        // Next find coordinates
        int startIndex = txt.indexOf("[");
        int endIndex = txt.indexOf("]"); 
        if(startIndex != -1 && endIndex != -1){
            startIndex += 1;
            String coords = txt.substring(startIndex, endIndex);

            int first_colon = coords.indexOf(":");
            int second_colon = coords.indexOf(":", first_colon+1);
            if(first_colon != -1 && second_colon != -1){
                int galaxy = Integer.parseInt(coords.substring(0, first_colon));
                int system = Integer.parseInt(coords.substring(first_colon+1, second_colon));
                int planet_num = Integer.parseInt(coords.substring(second_colon+1));
                return new Coords(galaxy, system, planet_num);
            }else{
                System.out.println("Unable to get full coords.");
                return null;
            }
        }else{
            System.out.println("Unable to find coordinates.");
            return null;
        }
    }
    
    protected String parsePlanetName(String splits[]){
        // Next get planet name
        int startIndex = splits[0].indexOf("Resourceson");
        int endIndex = splits[0].indexOf("[");
        if(startIndex != -1 && endIndex != -1){
            startIndex += 11;
            return splits[0].substring(startIndex, endIndex);
        }else{
            System.out.println("Unable to get planet name.");
            return null;
        }
    }
    
    protected Resources parseResources(String splits[]){
        // Read in resources
        String resource_names[] = {"Metal:", "Crystal:", "Deuterium:"};
        int resources[] = new int[3];
        for(int j = 0; j < resource_names.length; ++j){
            for(int i = 0; i < splits.length; ++i){
                if(splits[i].contains(resource_names[j])){
                    resources[j] = Integer.parseInt(splits[i+1].replace(",", ""));
                    break;
                }
            }
        }
        return new Resources(resources[0], resources[1], resources[2]);
    }
    
    protected void notifyOgameReaderListeners(Planet planet){
        for(OgamePlanetReaderListener listener: this.listeners){
            listener.ogameReadPerformed(planet);
        }
    }
    
    public void addOgameReaderListener(OgamePlanetReaderListener in){
        this.listeners.add(in);
    }
    
    public void removeOgameReaderListener(OgamePlanetReaderListener in){
        this.listeners.remove(in);
    }
    
    public void removeOgameReaderListener(int index){
        this.listeners.remove(index);
    }
    
    public void clearOgameReaderListeners(){
        this.listeners.clear();
    }
    
    public LinkedList<OgamePlanetReaderListener> getListeners(){
        return (LinkedList<OgamePlanetReaderListener>)(this.listeners.clone());
    }
}
